(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';

exports.__esModule = true;

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

/**
 * Hi :-) This is a class representing a Siema.
 */
var Siema = function () {
  /**
   * Create a Siema.
   * @param {Object} options - Optional settings object.
   */
  function Siema(options) {
    var _this = this;

    _classCallCheck(this, Siema);

    // Merge defaults with user's settings
    this.config = Siema.mergeSettings(options);

    // Resolve selector's type
    this.selector = typeof this.config.selector === 'string' ? document.querySelector(this.config.selector) : this.config.selector;

    // Early throw if selector doesn't exists
    if (this.selector === null) {
      throw new Error('Something wrong with your selector 😭');
    }

    // update perPage number dependable of user value
    this.resolveSlidesNumber();

    // Create global references
    this.selectorWidth = this.selector.offsetWidth;
    this.innerElements = [].slice.call(this.selector.children);
    this.currentSlide = this.config.loop ? this.config.startIndex % this.innerElements.length : Math.max(0, Math.min(this.config.startIndex, this.innerElements.length - this.perPage));
    this.transformProperty = Siema.webkitOrNot();

    // Bind all event handlers for referencability
    ['resizeHandler', 'touchstartHandler', 'touchendHandler', 'touchmoveHandler', 'mousedownHandler', 'mouseupHandler', 'mouseleaveHandler', 'mousemoveHandler', 'clickHandler'].forEach(function (method) {
      _this[method] = _this[method].bind(_this);
    });

    // Build markup and apply required styling to elements
    this.init();
  }

  /**
   * Overrides default settings with custom ones.
   * @param {Object} options - Optional settings object.
   * @returns {Object} - Custom Siema settings.
   */


  Siema.mergeSettings = function mergeSettings(options) {
    var settings = {
      selector: '.siema',
      duration: 200,
      easing: 'ease-out',
      perPage: 1,
      startIndex: 0,
      draggable: true,
      multipleDrag: true,
      threshold: 20,
      loop: false,
      rtl: false,
      onInit: function onInit() {},
      onChange: function onChange() {}
    };

    var userSttings = options;
    for (var attrname in userSttings) {
      settings[attrname] = userSttings[attrname];
    }

    return settings;
  };

  /**
   * Determine if browser supports unprefixed transform property.
   * Google Chrome since version 26 supports prefix-less transform
   * @returns {string} - Transform property supported by client.
   */


  Siema.webkitOrNot = function webkitOrNot() {
    var style = document.documentElement.style;
    if (typeof style.transform === 'string') {
      return 'transform';
    }
    if (typeof style.msTransform === "string") {
      return 'msTransform';
    }
    return 'WebkitTransform';
  };

  /**
   * Attaches listeners to required events.
   */


  Siema.prototype.attachEvents = function attachEvents() {
    // Resize element on window resize
    window.addEventListener('resize', this.resizeHandler);

    // If element is draggable / swipable, add event handlers
    if (this.config.draggable) {
      // Keep track pointer hold and dragging distance
      this.pointerDown = false;
      this.drag = {
        startX: 0,
        endX: 0,
        startY: 0,
        letItGo: null,
        preventClick: false
      };

      // Touch events
      this.selector.addEventListener('touchstart', this.touchstartHandler);
      this.selector.addEventListener('touchend', this.touchendHandler);
      this.selector.addEventListener('touchmove', this.touchmoveHandler);

      // Mouse events
      this.selector.addEventListener('mousedown', this.mousedownHandler);
      this.selector.addEventListener('mouseup', this.mouseupHandler);
      this.selector.addEventListener('mouseleave', this.mouseleaveHandler);
      this.selector.addEventListener('mousemove', this.mousemoveHandler);

      // Click
      this.selector.addEventListener('click', this.clickHandler);
    }
  };

  /**
   * Detaches listeners from required events.
   */


  Siema.prototype.detachEvents = function detachEvents() {
    window.removeEventListener('resize', this.resizeHandler);
    this.selector.removeEventListener('touchstart', this.touchstartHandler);
    this.selector.removeEventListener('touchend', this.touchendHandler);
    this.selector.removeEventListener('touchmove', this.touchmoveHandler);
    this.selector.removeEventListener('mousedown', this.mousedownHandler);
    this.selector.removeEventListener('mouseup', this.mouseupHandler);
    this.selector.removeEventListener('mouseleave', this.mouseleaveHandler);
    this.selector.removeEventListener('mousemove', this.mousemoveHandler);
    this.selector.removeEventListener('click', this.clickHandler);
  };

  /**
   * Builds the markup and attaches listeners to required events.
   */


  Siema.prototype.init = function init() {
    this.attachEvents();

    // hide everything out of selector's boundaries
    this.selector.style.overflow = 'hidden';

    // rtl or ltr
    this.selector.style.direction = this.config.rtl ? 'rtl' : 'ltr';

    // build a frame and slide to a currentSlide
    this.buildSliderFrame();

    this.config.onInit.call(this);
  };

  /**
   * Build a sliderFrame and slide to a current item.
   */


  Siema.prototype.buildSliderFrame = function buildSliderFrame() {
    var widthItem = this.selectorWidth / this.perPage;
    var itemsToBuild = this.config.loop ? this.innerElements.length + 2 * this.perPage : this.innerElements.length;

    // Create frame and apply styling
    this.sliderFrame = document.createElement('div');
    this.sliderFrame.style.width = widthItem * itemsToBuild + 'px';
    this.enableTransition();

    if (this.config.draggable) {
      this.selector.style.cursor = '-webkit-grab';
    }

    // Create a document fragment to put slides into it
    var docFragment = document.createDocumentFragment();

    // Loop through the slides, add styling and add them to document fragment
    if (this.config.loop) {
      for (var i = this.innerElements.length - this.perPage; i < this.innerElements.length; i++) {
        var element = this.buildSliderFrameItem(this.innerElements[i].cloneNode(true));
        docFragment.appendChild(element);
      }
    }
    for (var _i = 0; _i < this.innerElements.length; _i++) {
      var _element = this.buildSliderFrameItem(this.innerElements[_i]);
      docFragment.appendChild(_element);
    }
    if (this.config.loop) {
      for (var _i2 = 0; _i2 < this.perPage; _i2++) {
        var _element2 = this.buildSliderFrameItem(this.innerElements[_i2].cloneNode(true));
        docFragment.appendChild(_element2);
      }
    }

    // Add fragment to the frame
    this.sliderFrame.appendChild(docFragment);

    // Clear selector (just in case something is there) and insert a frame
    this.selector.innerHTML = '';
    this.selector.appendChild(this.sliderFrame);

    // Go to currently active slide after initial build
    this.slideToCurrent();
  };

  Siema.prototype.buildSliderFrameItem = function buildSliderFrameItem(elm) {
    var elementContainer = document.createElement('div');
    elementContainer.style.cssFloat = this.config.rtl ? 'right' : 'left';
    elementContainer.style.float = this.config.rtl ? 'right' : 'left';
    elementContainer.style.width = (this.config.loop ? 100 / (this.innerElements.length + this.perPage * 2) : 100 / this.innerElements.length) + '%';
    elementContainer.appendChild(elm);
    return elementContainer;
  };

  /**
   * Determinates slides number accordingly to clients viewport.
   */


  Siema.prototype.resolveSlidesNumber = function resolveSlidesNumber() {
    if (typeof this.config.perPage === 'number') {
      this.perPage = this.config.perPage;
    } else if (_typeof(this.config.perPage) === 'object') {
      this.perPage = 1;
      for (var viewport in this.config.perPage) {
        if (window.innerWidth >= viewport) {
          this.perPage = this.config.perPage[viewport];
        }
      }
    }
  };

  /**
   * Go to previous slide.
   * @param {number} [howManySlides=1] - How many items to slide backward.
   * @param {function} callback - Optional callback function.
   */


  Siema.prototype.prev = function prev() {
    var howManySlides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
    var callback = arguments[1];

    // early return when there is nothing to slide
    if (this.innerElements.length <= this.perPage) {
      return;
    }

    var beforeChange = this.currentSlide;

    if (this.config.loop) {
      var isNewIndexClone = this.currentSlide - howManySlides < 0;
      if (isNewIndexClone) {
        this.disableTransition();

        var mirrorSlideIndex = this.currentSlide + this.innerElements.length;
        var mirrorSlideIndexOffset = this.perPage;
        var moveTo = mirrorSlideIndex + mirrorSlideIndexOffset;
        var offset = (this.config.rtl ? 1 : -1) * moveTo * (this.selectorWidth / this.perPage);
        var dragDistance = this.config.draggable ? this.drag.endX - this.drag.startX : 0;

        this.sliderFrame.style[this.transformProperty] = 'translateX(' + (offset + dragDistance) + 'px)';
        this.currentSlide = mirrorSlideIndex - howManySlides;
      } else {
        this.currentSlide = this.currentSlide - howManySlides;
      }
    } else {
      this.currentSlide = Math.max(this.currentSlide - howManySlides, 0);
    }

    if (beforeChange !== this.currentSlide) {
      this.slideToCurrent(this.config.loop);
      this.config.onChange.call(this);
      if (callback) {
        callback.call(this);
      }
    }
  };

  /**
   * Go to next slide.
   * @param {number} [howManySlides=1] - How many items to slide forward.
   * @param {function} callback - Optional callback function.
   */


  Siema.prototype.next = function next() {
    var howManySlides = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
    var callback = arguments[1];

    // early return when there is nothing to slide
    if (this.innerElements.length <= this.perPage) {
      return;
    }

    var beforeChange = this.currentSlide;

    if (this.config.loop) {
      var isNewIndexClone = this.currentSlide + howManySlides > this.innerElements.length - this.perPage;
      if (isNewIndexClone) {
        this.disableTransition();

        var mirrorSlideIndex = this.currentSlide - this.innerElements.length;
        var mirrorSlideIndexOffset = this.perPage;
        var moveTo = mirrorSlideIndex + mirrorSlideIndexOffset;
        var offset = (this.config.rtl ? 1 : -1) * moveTo * (this.selectorWidth / this.perPage);
        var dragDistance = this.config.draggable ? this.drag.endX - this.drag.startX : 0;

        this.sliderFrame.style[this.transformProperty] = 'translateX(' + (offset + dragDistance) + 'px)';
        this.currentSlide = mirrorSlideIndex + howManySlides;
      } else {
        this.currentSlide = this.currentSlide + howManySlides;
      }
    } else {
      this.currentSlide = Math.min(this.currentSlide + howManySlides, this.innerElements.length - this.perPage);
    }
    if (beforeChange !== this.currentSlide) {
      this.slideToCurrent(this.config.loop);
      this.config.onChange.call(this);
      if (callback) {
        callback.call(this);
      }
    }
  };

  /**
   * Disable transition on sliderFrame.
   */


  Siema.prototype.disableTransition = function disableTransition() {
    this.sliderFrame.style.webkitTransition = 'all 0ms ' + this.config.easing;
    this.sliderFrame.style.transition = 'all 0ms ' + this.config.easing;
  };

  /**
   * Enable transition on sliderFrame.
   */


  Siema.prototype.enableTransition = function enableTransition() {
    this.sliderFrame.style.webkitTransition = 'all ' + this.config.duration + 'ms ' + this.config.easing;
    this.sliderFrame.style.transition = 'all ' + this.config.duration + 'ms ' + this.config.easing;
  };

  /**
   * Go to slide with particular index
   * @param {number} index - Item index to slide to.
   * @param {function} callback - Optional callback function.
   */


  Siema.prototype.goTo = function goTo(index, callback) {
    if (this.innerElements.length <= this.perPage) {
      return;
    }
    var beforeChange = this.currentSlide;
    this.currentSlide = this.config.loop ? index % this.innerElements.length : Math.min(Math.max(index, 0), this.innerElements.length - this.perPage);
    if (beforeChange !== this.currentSlide) {
      this.slideToCurrent();
      this.config.onChange.call(this);
      if (callback) {
        callback.call(this);
      }
    }
  };

  /**
   * Moves sliders frame to position of currently active slide
   */


  Siema.prototype.slideToCurrent = function slideToCurrent(enableTransition) {
    var _this2 = this;

    var currentSlide = this.config.loop ? this.currentSlide + this.perPage : this.currentSlide;
    var offset = (this.config.rtl ? 1 : -1) * currentSlide * (this.selectorWidth / this.perPage);

    if (enableTransition) {
      // This one is tricky, I know but this is a perfect explanation:
      // https://youtu.be/cCOL7MC4Pl0
      requestAnimationFrame(function () {
        requestAnimationFrame(function () {
          _this2.enableTransition();
          _this2.sliderFrame.style[_this2.transformProperty] = 'translateX(' + offset + 'px)';
        });
      });
    } else {
      this.sliderFrame.style[this.transformProperty] = 'translateX(' + offset + 'px)';
    }
  };

  /**
   * Recalculate drag /swipe event and reposition the frame of a slider
   */


  Siema.prototype.updateAfterDrag = function updateAfterDrag() {
    var movement = (this.config.rtl ? -1 : 1) * (this.drag.endX - this.drag.startX);
    var movementDistance = Math.abs(movement);
    var howManySliderToSlide = this.config.multipleDrag ? Math.ceil(movementDistance / (this.selectorWidth / this.perPage)) : 1;

    var slideToNegativeClone = movement > 0 && this.currentSlide - howManySliderToSlide < 0;
    var slideToPositiveClone = movement < 0 && this.currentSlide + howManySliderToSlide > this.innerElements.length - this.perPage;

    if (movement > 0 && movementDistance > this.config.threshold && this.innerElements.length > this.perPage) {
      this.prev(howManySliderToSlide);
    } else if (movement < 0 && movementDistance > this.config.threshold && this.innerElements.length > this.perPage) {
      this.next(howManySliderToSlide);
    }
    this.slideToCurrent(slideToNegativeClone || slideToPositiveClone);
  };

  /**
   * When window resizes, resize slider components as well
   */


  Siema.prototype.resizeHandler = function resizeHandler() {
    // update perPage number dependable of user value
    this.resolveSlidesNumber();

    // relcalculate currentSlide
    // prevent hiding items when browser width increases
    if (this.currentSlide + this.perPage > this.innerElements.length) {
      this.currentSlide = this.innerElements.length <= this.perPage ? 0 : this.innerElements.length - this.perPage;
    }

    this.selectorWidth = this.selector.offsetWidth;

    this.buildSliderFrame();
  };

  /**
   * Clear drag after touchend and mouseup event
   */


  Siema.prototype.clearDrag = function clearDrag() {
    this.drag = {
      startX: 0,
      endX: 0,
      startY: 0,
      letItGo: null,
      preventClick: this.drag.preventClick
    };
  };

  /**
   * touchstart event handler
   */


  Siema.prototype.touchstartHandler = function touchstartHandler(e) {
    // Prevent dragging / swiping on inputs, selects and textareas
    var ignoreSiema = ['TEXTAREA', 'OPTION', 'INPUT', 'SELECT'].indexOf(e.target.nodeName) !== -1;
    if (ignoreSiema) {
      return;
    }

    e.stopPropagation();
    this.pointerDown = true;
    this.drag.startX = e.touches[0].pageX;
    this.drag.startY = e.touches[0].pageY;
  };

  /**
   * touchend event handler
   */


  Siema.prototype.touchendHandler = function touchendHandler(e) {
    e.stopPropagation();
    this.pointerDown = false;
    this.enableTransition();
    if (this.drag.endX) {
      this.updateAfterDrag();
    }
    this.clearDrag();
  };

  /**
   * touchmove event handler
   */


  Siema.prototype.touchmoveHandler = function touchmoveHandler(e) {
    e.stopPropagation();

    if (this.drag.letItGo === null) {
      this.drag.letItGo = Math.abs(this.drag.startY - e.touches[0].pageY) < Math.abs(this.drag.startX - e.touches[0].pageX);
    }

    if (this.pointerDown && this.drag.letItGo) {
      e.preventDefault();
      this.drag.endX = e.touches[0].pageX;
      this.sliderFrame.style.webkitTransition = 'all 0ms ' + this.config.easing;
      this.sliderFrame.style.transition = 'all 0ms ' + this.config.easing;

      var currentSlide = this.config.loop ? this.currentSlide + this.perPage : this.currentSlide;
      var currentOffset = currentSlide * (this.selectorWidth / this.perPage);
      var dragOffset = this.drag.endX - this.drag.startX;
      var offset = this.config.rtl ? currentOffset + dragOffset : currentOffset - dragOffset;
      this.sliderFrame.style[this.transformProperty] = 'translateX(' + (this.config.rtl ? 1 : -1) * offset + 'px)';
    }
  };

  /**
   * mousedown event handler
   */


  Siema.prototype.mousedownHandler = function mousedownHandler(e) {
    // Prevent dragging / swiping on inputs, selects and textareas
    var ignoreSiema = ['TEXTAREA', 'OPTION', 'INPUT', 'SELECT'].indexOf(e.target.nodeName) !== -1;
    if (ignoreSiema) {
      return;
    }

    e.preventDefault();
    e.stopPropagation();
    this.pointerDown = true;
    this.drag.startX = e.pageX;
  };

  /**
   * mouseup event handler
   */


  Siema.prototype.mouseupHandler = function mouseupHandler(e) {
    e.stopPropagation();
    this.pointerDown = false;
    this.selector.style.cursor = '-webkit-grab';
    this.enableTransition();
    if (this.drag.endX) {
      this.updateAfterDrag();
    }
    this.clearDrag();
  };

  /**
   * mousemove event handler
   */


  Siema.prototype.mousemoveHandler = function mousemoveHandler(e) {
    e.preventDefault();
    if (this.pointerDown) {
      // if dragged element is a link
      // mark preventClick prop as a true
      // to detemine about browser redirection later on
      if (e.target.nodeName === 'A') {
        this.drag.preventClick = true;
      }

      this.drag.endX = e.pageX;
      this.selector.style.cursor = '-webkit-grabbing';
      this.sliderFrame.style.webkitTransition = 'all 0ms ' + this.config.easing;
      this.sliderFrame.style.transition = 'all 0ms ' + this.config.easing;

      var currentSlide = this.config.loop ? this.currentSlide + this.perPage : this.currentSlide;
      var currentOffset = currentSlide * (this.selectorWidth / this.perPage);
      var dragOffset = this.drag.endX - this.drag.startX;
      var offset = this.config.rtl ? currentOffset + dragOffset : currentOffset - dragOffset;
      this.sliderFrame.style[this.transformProperty] = 'translateX(' + (this.config.rtl ? 1 : -1) * offset + 'px)';
    }
  };

  /**
   * mouseleave event handler
   */


  Siema.prototype.mouseleaveHandler = function mouseleaveHandler(e) {
    if (this.pointerDown) {
      this.pointerDown = false;
      this.selector.style.cursor = '-webkit-grab';
      this.drag.endX = e.pageX;
      this.drag.preventClick = false;
      this.enableTransition();
      this.updateAfterDrag();
      this.clearDrag();
    }
  };

  /**
   * click event handler
   */


  Siema.prototype.clickHandler = function clickHandler(e) {
    // if the dragged element is a link
    // prevent browsers from folowing the link
    if (this.drag.preventClick) {
      e.preventDefault();
    }
    this.drag.preventClick = false;
  };

  /**
   * Remove item from carousel.
   * @param {number} index - Item index to remove.
   * @param {function} callback - Optional callback to call after remove.
   */


  Siema.prototype.remove = function remove(index, callback) {
    if (index < 0 || index >= this.innerElements.length) {
      throw new Error('Item to remove doesn\'t exist 😭');
    }

    // Shift sliderFrame back by one item when:
    // 1. Item with lower index than currenSlide is removed.
    // 2. Last item is removed.
    var lowerIndex = index < this.currentSlide;
    var lastItem = this.currentSlide + this.perPage - 1 === index;

    if (lowerIndex || lastItem) {
      this.currentSlide--;
    }

    this.innerElements.splice(index, 1);

    // build a frame and slide to a currentSlide
    this.buildSliderFrame();

    if (callback) {
      callback.call(this);
    }
  };

  /**
   * Insert item to carousel at particular index.
   * @param {HTMLElement} item - Item to insert.
   * @param {number} index - Index of new new item insertion.
   * @param {function} callback - Optional callback to call after insert.
   */


  Siema.prototype.insert = function insert(item, index, callback) {
    if (index < 0 || index > this.innerElements.length + 1) {
      throw new Error('Unable to inset it at this index 😭');
    }
    if (this.innerElements.indexOf(item) !== -1) {
      throw new Error('The same item in a carousel? Really? Nope 😭');
    }

    // Avoid shifting content
    var shouldItShift = index <= this.currentSlide > 0 && this.innerElements.length;
    this.currentSlide = shouldItShift ? this.currentSlide + 1 : this.currentSlide;

    this.innerElements.splice(index, 0, item);

    // build a frame and slide to a currentSlide
    this.buildSliderFrame();

    if (callback) {
      callback.call(this);
    }
  };

  /**
   * Prepernd item to carousel.
   * @param {HTMLElement} item - Item to prepend.
   * @param {function} callback - Optional callback to call after prepend.
   */


  Siema.prototype.prepend = function prepend(item, callback) {
    this.insert(item, 0);
    if (callback) {
      callback.call(this);
    }
  };

  /**
   * Append item to carousel.
   * @param {HTMLElement} item - Item to append.
   * @param {function} callback - Optional callback to call after append.
   */


  Siema.prototype.append = function append(item, callback) {
    this.insert(item, this.innerElements.length + 1);
    if (callback) {
      callback.call(this);
    }
  };

  /**
   * Removes listeners and optionally restores to initial markup
   * @param {boolean} restoreMarkup - Determinants about restoring an initial markup.
   * @param {function} callback - Optional callback function.
   */


  Siema.prototype.destroy = function destroy() {
    var restoreMarkup = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
    var callback = arguments[1];

    this.detachEvents();

    this.selector.style.cursor = 'auto';

    if (restoreMarkup) {
      var slides = document.createDocumentFragment();
      for (var i = 0; i < this.innerElements.length; i++) {
        slides.appendChild(this.innerElements[i]);
      }
      this.selector.innerHTML = '';
      this.selector.appendChild(slides);
      this.selector.removeAttribute('style');
    }

    if (callback) {
      callback.call(this);
    }
  };

  return Siema;
}();

exports['default'] = Siema;
},{}]},{},[1])